<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**************************************************************************
 *
 *   Copyright 2010 American Public Media Group
 *
 *   This file is part of AIR2.
 *
 *   AIR2 is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   AIR2 is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with AIR2.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/

/**
 * AirBatch Library
 *
 * Contains methods for fetching batches and batch_items.  Batch data can be
 * accessed from outside the batch controller, allowing it to be loaded inline
 * in requests from the AIR2 html view.
 *
 * @author rcavis
 * @package default
 */
class AirBatch {
    public $extra_fields = array(
        array('name' => 'batch_count', 'type' => 'int'),
        array('name' => 'batch_last_use', 'type' => 'date', 'dateFormat' => AIR2_DTIM_FORMAT),
        array('name' => 'batch_owner', 'type' => 'boolean'),
    );


    /**
     * Helper function to emulate the response of calling 'batch.json'
     *
     * @param array   $args arguments to apply to the query
     * @param string  $uuid (optional) uuid to fetch single
     * @param User    $user (optional) remote user for authz
     * @return array the result data
     */
    public function fetch($args, $uuid=null, &$user=null) {
        $q = AIR2_Query::create()->from('Batch a');
        $this->add_batch_args($q, $args);
        $this->add_batch_query_parts($q);

        // add authz
        if ($user) {
            Batch::query_may_read($q, $user, 'a');
        }

        // add regular query args
        $CI =& get_instance();
        $CI->airqargs->process_args($q, $args);

        // add default sorting
        $this->add_batch_default_sort($q);

        if ($uuid) {
            $q->addWhere('a.batch_uuid = ?', $uuid);
        }

        // execute the query
        $params = array('extra' => $this->extra_fields);
        return $CI->airquery->execute_query($q, $params);
    }


    /**
     * Emulate the response of calling 'batch/UUID/contents.json'
     *
     * @param Doctrine_Record $rec  (reference) the batch record
     * @param array   $args arguments to apply to the query
     * @param User    $user (optional) remote user for authz
     * @return array the result data
     */
    public function fetch_content(&$rec, $args, &$user) {
        $q = AIR2_Query::create()->from('BatchItem a');
        $q->addWhere("a.bitem_batch_id = ?", $rec->batch_id);
        $this->add_content_args($rec, $q, $args);
        $this->add_content_query_parts($q, $rec->batch_type);

        // TODO: add authz to content
        if ($user) {
            BatchItem::query_may_read($q, $user, 'a');
        }

        // add regular query args
        $CI =& get_instance();
        $CI->airqargs->process_args($q, $args);

        // add default sorting
        $this->add_content_default_sort($q);

        // execute the query
        $params = array('blacklist'   => array('bitem_xid'));
        return $CI->airquery->execute_query($q, $params);
    }


    /**
     * Create a generic query to fetch batches
     *
     * @param AIR2_Query $q
     */
    public function add_batch_query_parts(&$q) {
        $q->leftJoin('a.User u');

        // TODO: the last_use logic is fairly MySQL specific... find a way to
        // make it cross-database compatible!!
        $batch_count = 'select COUNT(*) from batch_item where bitem_batch_id = a.batch_id';
        $bitem_upd = 'select MAX(bitem_cre_dtim) from batch_item where bitem_batch_id = a.batch_id';
        $upd_logic = "GREATEST(batch_upd_dtim, COALESCE(($bitem_upd), 0))";
        $q->addSelect("($batch_count) as batch_count");
        $q->addSelect("($upd_logic) as batch_last_use");
        $q->addSelect("(batch_user_id = ".AIR2_REMOTE_USER_ID.") as batch_owner");
    }


    /**
     * Create a generic query to fetch batch contents
     *
     * @param AIR2_Query $q
     * @param char    $batch_type
     */
    public function add_content_query_parts(&$q, $batch_type) {
        $batchtbl = Batch::$TYPES[$batch_type]['batch'];
        $reltbl = Batch::$TYPES[$batch_type]['table'];
        $q->from("$batchtbl a");
        $q->leftJoin("a.$reltbl art");
        $q->leftJoin("a.BatchRelated r");
        BatchRelated::joinRelated($q, $batch_type, 'r');

        // for sources, join email and mail
        if ($reltbl == 'Source') {
            $q->leftJoin('art.SrcMailAddress sm WITH sm.smadd_primary_flag = true');
            $q->leftJoin('art.SrcEmail se WITH se.sem_primary_flag = true');
            $q->addSelect('sm.smadd_city as sort_city');
            $q->addSelect('se.sem_email as sort_email');
        }
    }


    /**
     * Applies filter arguments to a batch query
     *
     * @param AIR2_Query $q
     * @param array   $args the arguments to apply
     */
    public function add_batch_args(&$q, $args) {
        //process the args
        $filter = isset($args['q']) ? $args['q'] : null;
        $self = isset($args['self']) ? $args['self'] : null;
        $deleted = isset($args['deleted']) ? $args['deleted'] : null;
        $archived = isset($args['archived']) ? $args['archived'] : null;
        $type = isset($args['type']) ? $args['type'] : null;

        // filter by a query string
        if ($filter) {
            // create the custom search query
            $tmp = AIR2_Query::create();
            Batch::add_search_str($tmp, 'a', $filter, true);
            User::add_search_str($tmp, 'u', $filter, true);

            // assemble the parts, and parenthesize them into a where query
            $where = '';
            $params = $tmp->getFlattenedParams();
            $parts = $tmp->getDqlPart('where');
            foreach ($parts as $str) {
                $where .= " $str";
            }
            $q->addWhere("($where)", $params);
        }

        // show only batches owned by current user
        if ($self === 'true' || $self == 1) {
            $q->addWhere('a.batch_user_id = ?', AIR2_REMOTE_USER_ID);
        }

        // show batches marked as deleted (in addition to active)
        if ($deleted === 'true' || $deleted == 1) {
            $q->addWhere('(a.batch_status = "A" OR a.batch_status = "X")');
        }
        else {
            $q->addWhere('a.batch_status = "A"');
        }

        // show batches older than 90 days (in addition)
        if ($archived === 'true' || $archived == 1) {
            // nothing to do, for now... just show all
        }
        else {
            $ninetyDays = air2_date(strtotime(air2_date()." -90 days"));
            $q->addWhere('(batch_cre_dtim > ?)', $ninetyDays);
        }

        // show batches of particular type(s)
        if ($type && is_string($type)) {
            $q->whereIn('a.batch_type', str_split($type));
        }
    }


    /**
     * Applies filter arguments to a batch-content query
     *
     * @param Doctrine_Record $rec  (reference) the batch record
     * @param AIR2_Query $q
     * @param array   $args the arguments to apply
     */
    public function add_content_args(&$rec, &$q, $args) {
        //process the args
        $filter = isset($args['q']) ? $args['q'] : null;

        if ($filter) {
            $reltbl = Batch::$TYPES[$rec->batch_type]['table'];
            air2_add_query_search($q, $reltbl, null, $filter);
        }
    }


    /**
     * Add a default orderBy clause to a batch query
     *
     * @param Doctrine_Query $q
     */
    public function add_batch_default_sort(Doctrine_Query &$q) {
        $q->addOrderBy('batch_last_use DESC');
    }


    /**
     * Add a default orderBy clause to a batch content query
     *
     * @param Doctrine_Query $q
     */
    public function add_content_default_sort(Doctrine_Query &$q) {
        //$q->addOrderBy('');
    }


}
